package thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 刘远望
 * Date: 2025-05-24
 * Time: 22:25
 */

/**
 * 自己实现一个可重入锁
 * 1.在锁的内部记录当前是哪一个线程持有锁,后续每次进行加锁进行判定(线程相同就会跳过，不同则会另一个线程阻塞)
 * 2.通过计数器,记录当前加锁的次数,从而确定何时解锁
 * 区分大括号加锁的{对应的字节码指令与其他不同 同理}解锁指令也不同 所以能正确的计数
 */
//线程安全问题：
//第一种死锁(java自己已解决)
class Counter2 {
    private int count = 0;

    public void add() {
        count++;
    }

    public int get() {
        return count;
    }
}
public class Demo19 {
    public static void main(String[] args) throws InterruptedException {
        Counter2 counter = new Counter2();

        Thread thread = new Thread(() -> {
           for (int i = 0; i < 50000; i++) {
               //第一次进行加锁操作 能够成功(锁没有人用)
               //第二次进行加锁时,此时锁对象处于被占用的状态,第二次加锁就会触发阻塞状态
               //第一次加锁操作永远不会解开就会进入死锁状态
               //这里结果是正常的是因为java引入了可重入的概念
               /**
                * 可重入的概念：当某一个线程对一个锁加锁成功后，后续该线程再次针对这个锁进行加锁不会触发阻塞正常往下走 但是其他线程用这个对象加锁 则正常阻塞
                * 可重入锁的实现原理：关键就在于让锁对象内部保存,当前是哪个线程持有持有这把锁，后续有线程针对这个锁加锁的时候，
                * 对比一下，锁持有者的线程是否和当前加锁的线程是否是同一个
                */
               synchronized (counter) {//加锁(记录左大括号的数目+n)
                   synchronized (counter) {
                       counter.add();
                   }
               }//解锁(记录右大括号的数目-n)
           }
        });

        thread.start();
        thread.join();

        System.out.println("count= " + counter.get());
    }
}
